Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ

Node / meshtastic / Meshtastic-Android / files / .coderabbit.yaml

Displaying Raw β€’ Download

.coderabbit.yaml 7c6a6cc195a2248cd50ed7f2395451cabcd93fdc (7c6a6cc1) Text, 19.53 KB

T8b949e# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
T8b949e# CodeRabbit config β€” see https://docs.coderabbit.ai/getting-started/yaml-configuration
Tff7b72languageTb4b4b4: Ta5d6ffen-US

Tff7b72reviewsTb4b4b4:
T8b949e# chill = fewer nitpicks. CI already gates detekt/spotless/tests, and the
T8b949e# maintainers are experienced β€” we want CodeRabbit for substance, not lint noise.
Tff7b72profileTb4b4b4: Ta5d6ffchill
Tff7b72high_level_summaryTb4b4b4: Ta5d6fftrue
Tff7b72poemTb4b4b4: Ta5d6fffalse
T8b949e# Don't burn reviews on WIP. This repo opens lots of draft PRs; review on "ready".
T8b949e# Skip Renovate dependency updates β€” CI gates dependencies; we review for substance, not every bump.
Tff7b72auto_reviewTb4b4b4:
Tff7b72enabledTb4b4b4: Ta5d6fftrue
Tff7b72draftsTb4b4b4: Ta5d6fffalse
T8b949e# Review once when the PR goes ready, then on demand via `@coderabbitai review`.
T8b949e# Re-reviewing every push turned 6-commit PRs into 8 review rounds, because each
T8b949e# fix commit reopened a full pass. Batch the fixes, push, then ask for one re-review.
Tff7b72auto_incremental_reviewTb4b4b4: Ta5d6fffalse
Tff7b72ignore_usernamesTb4b4b4:
Tb4b4b4- Ta5d6ffrenovate
Tb4b4b4- Ta5d6ffrenovate[bot]
T8b949e# Workflow-authored PRs (changelog updates, scheduled firmware/hardware/
T8b949e# translation bumps) β€” machine-generated content, nothing to review.
Tb4b4b4- Ta5d6ffgithub-actions
Tb4b4b4- Ta5d6ffgithub-actions[bot]
Tff7b72ignore_title_keywordsTb4b4b4:
Tb4b4b4- Ta5d6ff"Ta5d6ffchore:Te6edf3 Ta5d6ffScheduledTe6edf3 Ta5d6ffupdatesTa5d6ff"
T8b949e# Stop reviewing once a PR is closed.
Tff7b72abort_on_closeTb4b4b4: Ta5d6fftrue

Tff7b72path_filtersTb4b4b4:
T8b949e# Generated / huge / non-source β€” don't review, just noise + token burn.
Tb4b4b4- Ta5d6ff"Ta5d6ff!**/build/**Ta5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ff!**/*.pngTa5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ff!**/*.webpTa5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ff!**/firmware_releases.jsonTa5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ff!**/emoji-data.jsonTa5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ff!**/flatpak-sources.jsonTa5d6ff"
T8b949e# Crowdin-managed translations β€” owned upstream, not hand-edited here.
Tb4b4b4- Ta5d6ff"Ta5d6ff!**/values-*/strings.xmlTa5d6ff"
T8b949e# Spec Kit scaffolding β€” vendored tooling, not hand-maintained here.
Tb4b4b4- Ta5d6ff"Ta5d6ff!.specify/**Ta5d6ff"

Tff7b72path_instructionsTb4b4b4:
T8b949e# Global review contract. Everything below this entry is area-specific detail;
T8b949e# this is what "a finding" means in this repo at all.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ff"Ta5d6ff**Ta5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72Report problems only. Every comment must name a concrete defect with evidence in the diff.
Tff7b72No praise, no style preferences, no speculative design feedback, no "consider extracting this"
Tff7b72on code that works.


Tff7b72FLAG these categories:

Tff7b721. Bugs β€” logic errors, off-by-one, null dereference, a missing `await`/`join`, dropped
Tff7b72cancellation, incorrect disposal order.

Tff7b722. Security β€” credential or key exposure, injection, insecure defaults, PII/location/crypto-key
Tff7b72material reaching a log sink or analytics payload.

Tff7b723. Correctness β€” behaviour that contradicts the PR description, the linked issue, or an existing
Tff7b72contract; a breaking public-API change with no justification.

Tff7b724. Behavioural contract changes β€” when a type is replaced, removed, or refactored, diff the OLD
Tff7b72implementation against the NEW one. Look for a removed `override`, a property that used to throw
Tff7b72on invalid access and now returns a default, an exception type that changed, and call sites that
Tff7b72depended on the removed type's specific behaviour.

Tff7b725. Weakened invariants β€” validation quietly relaxed during a refactor. Kotlin shapes:
Tff7b72`single()`/`first()` (throws) swapped for `firstOrNull()` (silently picks nothing);
Tff7b72a deleted `require`/`check`/`error`; `!!` replaced by `?: <default>` so a broken state becomes a
Tff7b72plausible value; an exhaustive `when` gaining an `else ->` branch that swallows new cases.

Tff7b726. Missing error handling at system boundaries β€” unvalidated input from the radio, a peer, an
Tff7b72MQTT broker, a deep link, or an intent extra. Do NOT flag missing null checks the Kotlin type
Tff7b72system already guarantees.

Tff7b727. Performance regressions β€” allocation in a hot path or a recomposition scope, N+1 database
Tff7b72queries, `runBlocking`/`Thread.sleep`/`.get()` on a coroutine or UI path, blocking
Tff7b72`getString()` on `Dispatchers.Default`, an unstable Compose parameter type that defeats skipping.

Tff7b728. Concurrency β€” unguarded shared mutable state, a read-decide-write sequence spanning a suspend
Tff7b72boundary, a mutex held across a suspending call, deadlock and lock-ordering risk.

Tff7b729. Temporal coupling and initialisation safety β€” `lateinit var` paired with a separate
Tff7b72`initialize()`/`start()` that a caller must remember, DI registrations that only work in one
Tff7b72resolution order, any pattern where a forgotten call is a runtime crash with no compile-time
Tff7b72signal.

Tff7b7210. Resource leaks β€” a `CoroutineScope` created and never cancelled, a `Closeable`/`AutoCloseable`
Tff7b72outside `use {}`, a registered receiver/listener/callback with no matching unregister, a BLE or
Tff7b72socket connection not closed on every exit path. Flag these even when the pattern was moved in
Tff7b72from elsewhere.

Tff7b7211. Dead code and stale comments β€” a comment describing behaviour the code no longer has, an
Tff7b72unused local or parameter, a materialising call whose result is never consumed.

Tff7b7212. Repository convention violations β€” see AGENTS.md and .skills/. Highest value: `java.*` or
Tff7b72`android.*` in `commonMain`, hardcoded user-facing strings, `runCatching` in a suspend context
Tff7b72instead of `safeCatching`, OkHttp instead of Ktor, hand-edits to generated or Crowdin-owned files.

Tff7b7213. Comment problems β€” a comment that contradicts the code, a workaround with no tracking link, a
Tff7b72parser or protocol handler that omits the raw wire shape needed to read the edge cases, and
Tff7b72privacy- or security-sensitive behaviour whose comment fails to explain scope and WHY. Do not ask
Tff7b72for comments on obvious code.


Tff7b72Do NOT flag: style already enforced by detekt, spotless, or .editorconfig; missing KDoc, unless a
Tff7b72new public API is entirely undocumented; refactoring suggestions for code the PR did not touch;
Tff7b72generated output (Wire protos, Crowdin locale files, baseline profiles, docs screenshots);
Tff7b72missing tests for docs-only, comment-only, or mechanical-rename changes.


Tff7b72Moved or extracted code counts as newly written. Review it on its merits and flag pre-existing
Tff7b72defects that came along with it, labelled "pre-existing β€” good opportunity to fix during this
Tff7b72refactor" so the author can weigh scope.


Tff7b72One problem per comment. Cite the exact line, symbol, or condition. Give a fix direction β€” a
Tff7b72snippet when the fix is not obvious. Never restate a finding already raised in an existing
Tff7b72review thread.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ff"Ta5d6ff**/commonMain/**Ta5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>
Tff7b72KMP common code. Flag any import of java.* or android.* β€” these break non-Android targets. Expect KMP equivalents instead (Okio, kotlinx Mutex/atomicfu, NumberFormatter.format() for floats).
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ff"Ta5d6ff**/*.ktTa5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>
Tff7b72Flag leftover // ... existing code ... placeholders, and any logging of PII, location, or cryptographic keys.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ff"Ta5d6ff**/src/**/strings.xmlTa5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>
Tff7b72New string resources must be alphabetically sorted (scripts/sort-strings.py). Flag out-of-order additions.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffbaselineprofile/
Tff7b72instructionsTb4b4b4: Ta5d6ffKeepTa5d6ff Ta5d6ffbaselineTa5d6ff Ta5d6ffprofileTa5d6ff Ta5d6ffgenerationTa5d6ff Ta5d6fftiedTa5d6ff Ta5d6fftoTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ff`google`Ta5d6ff Ta5d6ffflavorTa5d6ff Ta5d6ffandTa5d6ff Ta5d6ffconnectedTa5d6ff Ta5d6ffdevices/emulators,Ta5d6ff Ta5d6ffandTa5d6ff Ta5d6ffcommitTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffgeneratedTa5d6ff Ta5d6ffprofileTa5d6ff Ta5d6ffoutputTa5d6ff Ta5d6fftoTa5d6ff Ta5d6ff`androidApp/src/google/generated/baselineProfiles/baseline-prof.txt`.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffdocs/
Tff7b72instructionsTb4b4b4: Ta5d6ffTreatTa5d6ff Ta5d6ffnon-EnglishTa5d6ff Ta5d6fflocaleTa5d6ff Ta5d6fffoldersTa5d6ff Ta5d6ffasTa5d6ff Ta5d6ffCrowdin-managedTa5d6ff Ta5d6ffoutput;Ta5d6ff Ta5d6ffeditTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffEnglishTa5d6ff Ta5d6ffsourcesTa5d6ff Ta5d6ffunderTa5d6ff Ta5d6ff`docs/en/`Ta5d6ff Ta5d6ffandTa5d6ff Ta5d6ffregisterTa5d6ff Ta5d6ffnewTa5d6ff Ta5d6ffpagesTa5d6ff Ta5d6ffthroughTa5d6ff Ta5d6ff`feature/docs/`Ta5d6ff Ta5d6ffinsteadTa5d6ff Ta5d6ffofTa5d6ff Ta5d6ffhand-editingTa5d6ff Ta5d6fftranslatedTa5d6ff Ta5d6fflocaleTa5d6ff Ta5d6ffdirectories.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffscreenshot-tests/
Tff7b72instructionsTb4b4b4: Ta5d6ffWhenTa5d6ff Ta5d6ffupdatingTa5d6ff Ta5d6ffdocsTa5d6ff Ta5d6ffscreenshots,Ta5d6ff Ta5d6ffkeepTa5d6ff Ta5d6ff`docs-screenshots-manifest.txt`Ta5d6ff Ta5d6ffandTa5d6ff Ta5d6ff`docs-screenshot-aliases.properties`Ta5d6ff Ta5d6ffinTa5d6ff Ta5d6ffsyncTa5d6ff Ta5d6ffwithTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffgeneratedTa5d6ff Ta5d6fffiles,Ta5d6ff Ta5d6ffandTa5d6ff Ta5d6ffrerunTa5d6ff Ta5d6ff`copyDocsScreenshots`Ta5d6ff Ta5d6ffafterTa5d6ff Ta5d6ffregeneratingTa5d6ff Ta5d6ffscreenshots.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffdocs-screenshots/
Tff7b72instructionsTb4b4b4: Ta5d6ffKeepTa5d6ff Ta5d6ffthisTa5d6ff Ta5d6ffmoduleTa5d6ff Ta5d6ffgenerate-onlyTa5d6ff Ta5d6ffforTa5d6ff Ta5d6ffdocumentationTa5d6ff Ta5d6ffscreenshots;Ta5d6ff Ta5d6ffdoTa5d6ff Ta5d6ffnotTa5d6ff Ta5d6ffaddTa5d6ff Ta5d6ffitTa5d6ff Ta5d6fftoTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffCITa5d6ff Ta5d6ffvalidationTa5d6ff Ta5d6ffgateTa5d6ff Ta5d6ffthatTa5d6ff Ta5d6ffisTa5d6ff Ta5d6ffreservedTa5d6ff Ta5d6ffforTa5d6ff Ta5d6ff`screenshot-tests`.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffdesktopApp/
Tff7b72instructionsTb4b4b4: Ta5d6ffKeepTa5d6ff Ta5d6ffdesktopTa5d6ff Ta5d6ffreleaseTa5d6ff Ta5d6ffProGuardTa5d6ff Ta5d6ffrulesTa5d6ff Ta5d6ffalignedTa5d6ff Ta5d6ffwithTa5d6ff Ta5d6ff`androidApp/proguard-rules.pro`,Ta5d6ff Ta5d6ffandTa5d6ff Ta5d6ffpreserveTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffdesktop-specificTa5d6ff Ta5d6ffruntimeTa5d6ff Ta5d6ffwiringTa5d6ff Ta5d6ffneededTa5d6ff Ta5d6ffforTa5d6ff Ta5d6ff`Dispatchers.Main`Ta5d6ff Ta5d6ffonTa5d6ff Ta5d6ffJVM.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffandroidApp/
Tff7b72instructionsTb4b4b4: Ta5d6ffKeepTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffAndroidTa5d6ff Ta5d6ffapp’sTa5d6ff Ta5d6ff`MeshService`Ta5d6ff Ta5d6ffdeclarationTa5d6ff Ta5d6ffandTa5d6ff Ta5d6ffmanifestTa5d6ff Ta5d6ffwiringTa5d6ff Ta5d6ffinTa5d6ff Ta5d6ffsyncTa5d6ff Ta5d6ffwithTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffimplementationTa5d6ff Ta5d6ffthatTa5d6ff Ta5d6fflivesTa5d6ff Ta5d6ffinTa5d6ff Ta5d6ff`core:service`.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffcore/service/
Tff7b72instructionsTb4b4b4: Ta5d6ffKeepTa5d6ff Ta5d6ff`RadioControllerImpl`Ta5d6ff Ta5d6ffcomposedTa5d6ff Ta5d6fffromTa5d6ff Ta5d6ffitsTa5d6ff Ta5d6ffsub-controllersTa5d6ff Ta5d6ffviaTa5d6ff Ta5d6ffinterfaceTa5d6ff Ta5d6ffdelegation;Ta5d6ff Ta5d6ffadminTa5d6ff Ta5d6ffsendsTa5d6ff Ta5d6ffareTa5d6ff Ta5d6fffire-and-forget,Ta5d6ff Ta5d6ffandTa5d6ff Ta5d6ffanyTa5d6ff Ta5d6ffconfigTa5d6ff Ta5d6ffmutationTa5d6ff Ta5d6ffmustTa5d6ff Ta5d6ffgoTa5d6ff Ta5d6ffthroughTa5d6ff Ta5d6ff`editSettingsTa5d6ff Ta5d6ff{Ta5d6ff Ta5d6ff}`Ta5d6ff Ta5d6fftransactions.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6fffeature/docs/
Tff7b72instructionsTb4b4b4: Ta5d6ffTreatTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffComposeTa5d6ff Ta5d6ffresourcesTa5d6ff Ta5d6ffunderTa5d6ff Ta5d6ff`src/commonMain/composeResources/files/`Ta5d6ff Ta5d6ffasTa5d6ff Ta5d6ffgeneratedTa5d6ff Ta5d6ffoutputTa5d6ff Ta5d6fffromTa5d6ff Ta5d6ff`/docs/en/**`Ta5d6ff Ta5d6ffandTa5d6ff Ta5d6fftranslatedTa5d6ff Ta5d6ffdocsTa5d6ff Ta5d6ffsyncTa5d6ff Ta5d6fftasks;Ta5d6ff Ta5d6ffdoTa5d6ff Ta5d6ffnotTa5d6ff Ta5d6ffhand-editTa5d6ff Ta5d6ffthoseTa5d6ff Ta5d6ffcopiedTa5d6ff Ta5d6fffiles.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6fffeature/map/
Tff7b72instructionsTb4b4b4: Ta5d6ffRouteTa5d6ff Ta5d6ffmapTa5d6ff Ta5d6ffaccessTa5d6ff Ta5d6ffthroughTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffinjectedTa5d6ff Ta5d6ff`CompositionLocal`Ta5d6ff Ta5d6ffproviderTa5d6ff Ta5d6ffcontracts;Ta5d6ff Ta5d6ffdoTa5d6ff Ta5d6ffnotTa5d6ff Ta5d6ffdependTa5d6ff Ta5d6ffdirectlyTa5d6ff Ta5d6ffonTa5d6ff Ta5d6ffGoogleTa5d6ff Ta5d6ffMapsTa5d6ff Ta5d6fforTa5d6ff Ta5d6ffosmdroidTa5d6ff Ta5d6fffromTa5d6ff Ta5d6fffeatureTa5d6ff Ta5d6ffcode.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6fffeature/car/
Tff7b72instructionsTb4b4b4: Ta5d6ffRunTa5d6ff Ta5d6ffunitTa5d6ff Ta5d6fftestsTa5d6ff Ta5d6ffwithTa5d6ff Ta5d6ff`./gradlewTa5d6ff Ta5d6ff:feature:car:testGoogleDebugUnitTest`,Ta5d6ff Ta5d6ffandTa5d6ff Ta5d6ffkeepTa5d6ff Ta5d6ffRobolectricTa5d6ff Ta5d6ffpinnedTa5d6ff Ta5d6fftoTa5d6ff Ta5d6ffSDKTa5d6ff Ta5d6ff36Ta5d6ff Ta5d6ffforTa5d6ff Ta5d6ffthisTa5d6ff Ta5d6ffmodule.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffcore/database/
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72Review focus: schema compatibility. A `@Database` version bump must ship a new
Tff7b72`core/database/schemas/<n>.json` AND an (n-1)β†’n test under `androidHostTest` that inserts rows at
Tff7b72the old version, migrates, and asserts row count and column values survive β€” not merely that the
Tff7b72migration executes. A column going nullable must assert both that pre-existing values are retained
Tff7b72and that the new NULL state is reachable. Flag `@Insert`+`@Update` pairs that should be `@Upsert`,
Tff7b72single-row queries missing `LIMIT 1`, and N+1 patterns (a loop issuing single-row queries) that
Tff7b72should be a chunked `WHERE IN`.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ffcore/network/
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72Review focus: request lifecycle. Timeouts and base URLs come from `HttpClientDefaults`; flag
Tff7b72hardcoded timeouts or absolute URLs in callers. Check every failure path for cancellation
Tff7b72propagation (`safeCatching`, not `runCatching`) and for a response body that is closed on error as
Tff7b72well as success.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ff.github/workflows/
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72Review focus: unintended side effects. Flag a change that widens a trigger (especially
Tff7b72`pull_request_target` and anything granting write scopes to fork-authored code), a secret exposed
Tff7b72to an untrusted context, a cache key that lets one job poison another, and an unpinned third-party
Tff7b72action. Job-level `continue-on-error` or a removed `--fail`-style guard silently converts a broken
Tff7b72gate into a green tick β€” flag it.
Tb4b4b4- Tff7b72pathTb4b4b4: Ta5d6ff"Ta5d6ff**/*.gradle.ktsTa5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72Review focus: build correctness over cleanliness. Several idioms here are load-bearing and look
Tff7b72redundant β€” do not suggest removing an explicit dependency declaration, a duplicated exclusion, or
Tff7b72an apparently no-op configuration block without evidence from the diff that it is dead. Flag
Tff7b72changes that alter variant/flavor wiring, drop a keep rule, or make a task's inputs/outputs
Tff7b72untracked (which silently disables caching and up-to-date checks).

T8b949e# Every CodeRabbit tool is enabled by default, so this block only ever needs to
T8b949e# turn things OFF or configure them. detekt is off because CI owns it (Zero Lint
T8b949e# Tolerance gate) and duplicate comments were the noise we removed. The scanners
T8b949e# CI doesn't run β€” gitleaks, shellcheck, actionlint, zizmor, semgrep, trivy,
T8b949e# presidio (PII), buf (protobuf) β€” are already on by default; don't re-list them.
Tff7b72toolsTb4b4b4:
Tff7b72detektTb4b4b4:
Tff7b72enabledTb4b4b4: Ta5d6fffalse
T8b949e# Custom AST rules mechanically enforce the recurring defect classes that prose
T8b949e# can't. See .coderabbit/ast-grep-rules/ and .skills/code-review/SKILL.md.
T8b949e# essential_rules stays on (default) β€” these are additive.
Tff7b72ast-grepTb4b4b4:
Tff7b72rule_dirsTb4b4b4:
Tb4b4b4- Ta5d6ff"Ta5d6ff.coderabbit/ast-grep-rulesTa5d6ff"

T8b949e# Auto-generated docstrings/tests/autofix are noisy for a repo with strict
T8b949e# human-authored KDoc and KMP-aware tests; leave finishing touches off.
Tff7b72finishing_touchesTb4b4b4:
Tff7b72docstringsTb4b4b4:
Tff7b72enabledTb4b4b4: Ta5d6fffalse
Tff7b72unit_testsTb4b4b4:
Tff7b72enabledTb4b4b4: Ta5d6fffalse

T8b949e# No KDoc-coverage mandate in this repo; the default warning-at-80% check
T8b949e# would nag every PR. PR titles are already linted by CI
T8b949e# (.github/workflows/pull-request-target.yml), so no title check here either.
Tff7b72pre_merge_checksTb4b4b4:
Tff7b72docstringsTb4b4b4:
Tff7b72modeTb4b4b4: Ta5d6ff"Ta5d6ffoffTa5d6ff"
T8b949e# Defect classes that survive review-by-prose because they are about what is
T8b949e# ABSENT from a diff β€” a sibling call site left unfixed, a test that would still
T8b949e# pass with the fix reverted, a regression nobody covered, a behaviour quietly
T8b949e# dropped while code moved files. A per-file reviewer never sees these; a
T8b949e# whole-PR check does. Warning, not error: all four are judgment calls and a
T8b949e# false positive must not block a merge.
Tff7b72custom_checksTb4b4b4:
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ff"Ta5d6ffSiblingTe6edf3 Ta5d6ffcallTe6edf3 Ta5d6ffsitesTe6edf3 Ta5d6ffandTe6edf3 Ta5d6ffpresenceTe6edf3 Ta5d6ffsemanticsTa5d6ff"
Tff7b72modeTb4b4b4: Ta5d6ff"Ta5d6ffwarningTa5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72When a diff changes how an absent value is represented β€” making a field nullable,
Tff7b72removing a zero-guard, or adding a presence check β€” verify EVERY call site of that
Tff7b72field was updated, not just the one the bug was reported against. Ambient temperature
Tff7b72was fixed in NodeItem.kt while its sibling NodeItemCompact.kt kept the zero-guard.
Tff7b72Name any unfixed sibling explicitly. Also flag a new field defaulting to 0 where 0 is
Tff7b72a physically reachable value on that scale (RSSI, temperature, current, voltage,
Tff7b72particulate concentration). Two exceptions, do NOT flag either: humidity, where 0 %RH
Tff7b72is unreachable and the guard is intentional and tested; and the proto `rx_snr`, which
Tff7b72has no presence upstream, so its 0f ambiguity cannot be fixed app-side. An app-level
Tff7b72SNR field that IS nullable is still in scope.
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ff"Ta5d6ffTestsTe6edf3 Ta5d6ffproveTe6edf3 Ta5d6fftheTe6edf3 Ta5d6ffpath,Te6edf3 Ta5d6ffnotTe6edf3 Ta5d6fftheTe6edf3 Ta5d6ffendTe6edf3 Ta5d6ffstateTa5d6ff"
Tff7b72modeTb4b4b4: Ta5d6ff"Ta5d6ffwarningTa5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72For each added or changed test, decide whether it would still pass if the production
Tff7b72code it covers were reverted. Flag tests that seed a fake's backing store and then
Tff7b72assert the value comes back, tests that assert only a collection's size rather than
Tff7b72which items survived, and tests asserting emission ORDER under Dispatchers.Unconfined
Tff7b72(not a stable contract). A test must assert the side effect only the intended path
Tff7b72produces β€” a call counter, a request issued, a cache written.
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ff"Ta5d6ffRegressionTe6edf3 Ta5d6ffcoverageTe6edf3 Ta5d6ffforTe6edf3 Ta5d6ffchangedTe6edf3 Ta5d6ffbehaviorTa5d6ff"
Tff7b72modeTb4b4b4: Ta5d6ff"Ta5d6ffwarningTa5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72Do not stop at "tests pass" or "there are tests". For each non-trivial production change in
Tff7b72the diff, work through four steps and report only the gaps.


Tff7b721. Changed behaviour β€” name the concrete code path, function, or configuration key from the
Tff7b72diff whose behaviour changed.

Tff7b722. Observable surfaces β€” which of these can see the change: public API, the mesh/radio
Tff7b72protocol handling, persisted database rows, DataStore preferences, Compose UI state,
Tff7b72navigation, notifications, the foreground service lifecycle, BLE/serial/TCP transport,
Tff7b72MQTT, widgets, Android Auto, the desktop app, or R8/ProGuard-shaped release behaviour.

Tff7b723. Regression risks β€” the specific ways this could break a working scenario: ordering and
Tff7b72timing changes, reconnect and retry paths, process death and state restore, schema
Tff7b72compatibility for rows written by an older build, cross-module call sites, flavor
Tff7b72differences (google vs fdroid), and platform differences (Android vs JVM vs iOS targets).

Tff7b724. Coverage gap β€” name the test that should exist and does not.


Tff7b72A bug fix needs a test that FAILS without the fix. A test that only exercises the happy path,
Tff7b72or a regenerated snapshot/golden file, does not prove a behaviour change. Flag a PR whose only
Tff7b72test evidence is an updated screenshot golden, an updated Room schema JSON, or a regenerated
Tff7b72baseline profile when the change is behavioural.


Tff7b72State each finding as: impacted code path, the regression risk, the missing test shape. Be
Tff7b72specific enough that the author can write the test from the comment.


Tff7b72Do NOT ask for tests for: documentation-only or comment-only changes, mechanical renames,
Tff7b72dependency version bumps, or refactors the diff shows to be behaviour-preserving. Do not
Tff7b72demand a test category for a surface the change cannot reach β€” a `commonMain` formatting
Tff7b72helper does not need a transport test.
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ff"Ta5d6ffMovedTe6edf3 Ta5d6ffcodeTe6edf3 Ta5d6ffdiffedTe6edf3 Ta5d6ffagainstTe6edf3 Ta5d6ffitsTe6edf3 Ta5d6fforiginalTa5d6ff"
Tff7b72modeTb4b4b4: Ta5d6ff"Ta5d6ffwarningTa5d6ff"
Tff7b72instructionsTb4b4b4: Tb4b4b4>Tb4b4b4-
Tff7b72Applies when the diff deletes a type/function in one file and adds something similar
Tff7b72elsewhere, or extracts code into a new file or module. Treat the moved code as newly written
Tff7b72and compare the OLD implementation against the NEW one line by line.


Tff7b72Flag any of the following that the move introduced silently:

Tff7b72- a removed `override`, or an interface member the new type no longer implements;

Tff7b72- a changed exception contract β€” something that threw now returns a default, or vice versa;

Tff7b72- a dropped `require`/`check`/`init` block validation, or a narrowed visibility widened;

Tff7b72- a default parameter value that changed, which alters every call site that omitted it;

Tff7b72- a nullability change on a numeric field, which is the presence-vs-sentinel-zero class;

Tff7b72- a lost `@Serializable`/`@Parcelize`/Koin annotation, or a scope change (`@Single` to
Tff7b72`@Factory`) that alters instance lifetime;

Tff7b72- a coroutine scope, dispatcher, or `SharingStarted` policy that changed during the move.


Tff7b72Then check the call sites of the removed declaration: every caller that relied on the old
Tff7b72behaviour must still be correct. Name any caller the PR left on the old assumption.


Tff7b72Pre-existing defects carried into the new location are in scope β€” label them "pre-existing β€”
Tff7b72good opportunity to fix during this refactor" so the author can decide on scope. Do not flag
Tff7b72a move that the diff shows to be genuinely mechanical.

Tff7b72knowledge_baseTb4b4b4:
T8b949e# Learnings are how a confirmed finding stops recurring on the next PR. Pin the
T8b949e# scope to this repo: the default `auto` already resolves to `local` for public
T8b949e# repos, but being explicit keeps it from shifting if visibility ever changes.
Tff7b72learningsTb4b4b4:
Tff7b72scopeTb4b4b4: Ta5d6fflocal
T8b949e# Feed CodeRabbit the same guidance human/AI contributors follow, including
T8b949e# the repo-specific .skills/ modules and Copilot path instructions it
T8b949e# wouldn't pick up by default.
Tff7b72code_guidelinesTb4b4b4:
Tff7b72enabledTb4b4b4: Ta5d6fftrue
Tff7b72filePatternsTb4b4b4:
Tb4b4b4- Ta5d6ff"Ta5d6ffAGENTS.mdTa5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ffCLAUDE.mdTa5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ff.skills/**/SKILL.mdTa5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ff.github/copilot-instructions.mdTa5d6ff"
Tb4b4b4- Ta5d6ff"Ta5d6ff.github/instructions/*.instructions.mdTa5d6ff"

Served by rngit 1.5.2 - Generated in 0.1s